/**
 * @file ringflow.h
 *
 * @brief Ring buffers
 *
 * Ringbuffer implementation store/access arbitrary binary data
 *
 * author : zhangerhu
 *
 */
#ifndef _RINGFLOW_H_
#define _RINGFLOW_H_

#ifdef __cplusplus
extern "C"
{
#endif

#define BUF_USED 0Xff000000
#define BUF_FREE 0X00000000
#define RBUF_ALIGN 4

    typedef enum
    {
        RBUF_MODE_BUF_IN = 0,
        RBUF_MODE_BUF_OUT
    } rbuf_mode_t;

    typedef enum
    {
        RBUF_MODE_SIMPLE = 0,
        RBUF_MODE_SHARE
    } rbuf_run_mode_t;

    typedef enum
    {
        RBUF_CREATE_SERVER_ROLE = 0,
        RBUF_CREATE_CLIENT_ROLE
    } rbuf_create_role;

    struct _ring_flow_s
    {
        char *buf; // the buffer
        char *buf_s;
        char *buf_c;
        int block_size;  // block size
        int block_count; // block count
        int size;        // buffer size
        int used;        // used size
        int rfx;         // read offset
        int wfx;         // write offset
        int mode;        // out buffer mode
        int run_mode;    // run mode
        int role;        // create role
    };

    /**
     * @brief ringbuffer handler
     */
    typedef struct _ring_flow_s rflow_t;

    /**
     * @brief Create a new ringbuffer, buffer size is (block_size * block_count)
     * @param buf : A block of memory in a ring buffer that, if empty, internally requests a cache of its own (in bytes)
     * @param block_size  : The size of a cache in a ring buffer (in bytes)
     * @param block_count : The number of caches in the ring buffer
     * @param mode        : The buffer mode, RBUF_MODE_BUF_IN or RBUF_MODE_BUF_OUT
     * @param role        : The create role, RBUF_CREATE_SERVER_ROLE or RBUF_CREATE_CLIENT_ROLE
     * @return : A pointer to an initialized rflow_t structure
     */
    rflow_t *rbuf_create(char *buf, int block_size, int block_count, int mode, int role);

    /**
     * @brief Write the specified amount of bytes into the ringbuffer
     * @param rbuf  : A valid pointer to a rbuf_t structure
     * @param in   : A pointer to the data to copy into the ringbuffer
     * @param size : The amount of bytes to be copied
     * @return     : The amount of bytes actually copied into the ringbuffer
     */
    int rbuf_write(rflow_t *rbuf, char *data, int len);

    /**
     * @brief Read the specified amount of bytes from the ringbuffer
     * @param rbuf  : A valid pointer to a rbuf_t structure
     * @param out  : A valid pointer initialized to store the read data
     * @param size : The amount of bytes to read and copy to the memory
     *               pointed by 'buf'
     * @return     : The amount of bytes actually read from the ringbuffer
     */
    int rbuf_read(rflow_t *rbuf, char *out, int len);

    /**
     * @brief Read the specified amount of bytes from the ringbuffer
     * @param rbuf  : A valid pointer to a rbuf_t structure
     * @param out  : A valid pointer initialized to store the read data
     * @param size : The amount of bytes to read and copy to the memory
     *               pointed by 'buf'
     * @param post : The offset of ringbuffer
     * @return     : The amount of bytes actually read from the ringbuffer
     */
    int rbuf_read_post(rflow_t *rbuf, char *out, int len, int *post);

    /**
     * @brief Release all resources associated to the rbuf_t structure
     * @param rbuf : A valid pointer to a rflow_t structure
     * @note： The external buffer must be released by the applicant
     */
    void rbuf_destroy(rflow_t *rbuf);

#ifdef __cplusplus
}
#endif

#endif